home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / Tools / cproto-3.0 / semantic.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-03  |  20.7 KB  |  854 lines

  1. /* $Id: semantic.c 3.8 1993/05/26 01:36:41 cthuang Exp $
  2.  *
  3.  * Semantic actions executed by the parser of the
  4.  * C function prototype generator.
  5.  */
  6. #include <stdio.h>
  7. #include "cproto.h"
  8. #include "semantic.h"
  9.  
  10. /* Head function declarator in a prototype or function definition */
  11. static Declarator *func_declarator;
  12.  
  13. /* Role of the function declarator
  14.  * FUNC_PROTO if it is the declarator in a function prototype.
  15.  * FUNC_DEF if it is the declarator in a function definition.
  16.  */
  17. static int where;
  18.  
  19. /* Output format to use */
  20. static int format;
  21.  
  22. /* Initialize a new declaration specifier part.
  23.  */
  24. void
  25. new_decl_spec (decl_spec, text, offset, flags)
  26. DeclSpec *decl_spec;
  27. char *text;
  28. long offset;
  29. int flags;
  30. {
  31.     decl_spec->text = xstrdup(text);
  32.     decl_spec->begin = offset;
  33.     decl_spec->flags = flags;
  34. }
  35.  
  36. /* Free storage used by a declaration specifier part.
  37.  */
  38. void
  39. free_decl_spec (decl_spec)
  40. DeclSpec *decl_spec;
  41. {
  42.     free(decl_spec->text);
  43. }
  44.  
  45. /* Create a new string by joining two strings with a space between them.
  46.  * Return a pointer to the resultant string.
  47.  * If out of memory, output an error message and exit.
  48.  */
  49. static char *
  50. concat_string (a, b)
  51. char *a, *b;
  52. {
  53.     char *result;
  54.  
  55.     result = xmalloc(strlen(a) + strlen(b) + 2);
  56.     strcpy(result, a);
  57.     strcat(result, " ");
  58.     strcat(result, b);
  59.     return result;
  60. }
  61.  
  62. /* Append two declaration specifier parts together.
  63.  */
  64. void
  65. join_decl_specs (result, a, b)
  66. DeclSpec *result, *a, *b;
  67. {
  68.     result->text = concat_string(a->text, b->text);
  69.     result->flags = a->flags | b->flags;
  70.     result->begin = a->begin;
  71. }
  72.  
  73. /* Output an error message if the declaration specifier is an untagged
  74.  * struct, union or enum.
  75.  */
  76. void
  77. check_untagged (decl_spec)
  78. DeclSpec *decl_spec;
  79. {
  80.     if (strstr(decl_spec->text, "struct {}") != NULL) {
  81.     put_error();
  82.     fputs("untagged struct declaration\n", stderr);
  83.     } else if (strstr(decl_spec->text, "union {}") != NULL) {
  84.     put_error();
  85.     fputs("untagged union declaration\n", stderr);
  86.     } else if (strstr(decl_spec->text, "enum {}") != NULL) {
  87.     put_error();
  88.     fputs("untagged enum declaration\n", stderr);
  89.     }
  90. }
  91.  
  92. /* Allocate and initialize a declarator.
  93.  */
  94. Declarator *
  95. new_declarator (text, name, offset)
  96. char *text, *name;
  97. long offset;
  98. {
  99.     Declarator *d;
  100.  
  101.     d = (Declarator *)xmalloc(sizeof(Declarator));
  102.     d->text = xstrdup(text);
  103.     d->name = xstrdup(name);
  104.     d->begin = offset;
  105.     d->begin_comment = d->end_comment = 0;
  106.     d->func_def = FUNC_NONE;
  107.     new_ident_list(&d->params);
  108.     d->head = d;
  109.     d->func_stack = NULL;
  110.     d->pointer = FALSE;
  111.     return d;
  112. }
  113.  
  114. /* Free storage used by a declarator.
  115.  */
  116. void
  117. free_declarator (d)
  118. Declarator *d;
  119. {
  120.     free(d->text);
  121.     free(d->name);
  122.     free_param_list(&d->params);
  123.     if (d->func_stack != NULL)
  124.     free_declarator(d->func_stack);
  125.     free(d);
  126. }
  127.  
  128. /* Initialize a declarator list and add the given declarator to it.
  129.  */
  130. void
  131. new_decl_list (decl_list, declarator)
  132. DeclaratorList *decl_list;
  133. Declarator *declarator;
  134. {
  135.     decl_list->first = decl_list->last = declarator;
  136.     declarator->next = NULL;
  137. }
  138.  
  139. /* Free storage used by the declarators in the declarator list.
  140.  */
  141. void
  142. free_decl_list (decl_list)
  143. DeclaratorList *decl_list;
  144. {
  145.     Declarator *d, *next;
  146.  
  147.     d = decl_list->first;
  148.     while (d != NULL) {
  149.     next = d->next;
  150.     free_declarator(d);
  151.     d = next;
  152.     }
  153. }
  154.  
  155. /* Add the declarator to the declarator list.
  156.  */
  157. void
  158. add_decl_list (to, from, declarator)
  159. DeclaratorList *to, *from;
  160. Declarator *declarator;
  161. {
  162.     to->first = from->first;
  163.     from->last->next = declarator;
  164.     to->last = declarator;
  165.     to->last->next = NULL;
  166. }
  167.  
  168. /* Create a new parameter structure.
  169.  */
  170. Parameter *
  171. new_parameter (decl_spec, declarator)
  172. DeclSpec *decl_spec;
  173. Declarator *declarator;
  174. {
  175.     Parameter *param;
  176.     param = (Parameter *)xmalloc(sizeof(Parameter));
  177.  
  178.     if (decl_spec == NULL) {
  179.     new_decl_spec(¶m->decl_spec, "", 0L, DS_NONE);
  180.     } else {
  181.     param->decl_spec = *decl_spec;
  182.     }
  183.  
  184.     if (declarator == NULL) {
  185.     declarator = new_declarator("", "", 0L);
  186.     }
  187.     param->declarator = declarator;
  188.  
  189.     param->comment = NULL;
  190.     return param;
  191. }
  192.  
  193. /* Free the storage used by the parameter.
  194.  */
  195. void
  196. free_parameter (param)
  197. Parameter *param;
  198. {
  199.     free_decl_spec(¶m->decl_spec);
  200.     free_declarator(param->declarator);
  201.     if (param->comment != NULL)
  202.     free(param->comment);
  203.     free(param);
  204. }
  205.  
  206. /* Return TRUE if the parameter is void.
  207.  */
  208. static boolean
  209. is_void_parameter (p)
  210. Parameter *p;
  211. {
  212.     return p == NULL || (strcmp(p->decl_spec.text, "void") == 0 &&
  213.      p->declarator->text[0] == '\0');
  214. }
  215.  
  216. /* Initialize a list of function parameters.
  217.  */
  218. void
  219. new_param_list (param_list, param)
  220. ParameterList *param_list;
  221. Parameter *param;
  222. {
  223.     param_list->first = param_list->last = param;
  224.     param->next = NULL;
  225.  
  226.     param_list->begin_comment = param_list->end_comment = 0;
  227.     param_list->comment = NULL;
  228. }
  229.  
  230. /* Free storage used by the elements in the function parameter list.
  231.  */
  232. void
  233. free_param_list (param_list)
  234. ParameterList *param_list;
  235. {
  236.     Parameter *p, *next;
  237.  
  238.     p = param_list->first;
  239.     while (p != NULL) {
  240.     next = p->next;
  241.     free_parameter(p);
  242.     p = next;
  243.     }
  244.  
  245.     if (param_list->comment != NULL)
  246.     free(param_list->comment);
  247. }
  248.  
  249. /* Add the parameter to the function parameter list.
  250.  */
  251. void
  252. add_param_list (to, from, param)
  253. ParameterList *to, *from;
  254. Parameter *param;
  255. {
  256.     to->first = from->first;
  257.     from->last->next = param;
  258.     to->last = param;
  259.     param->next = NULL;
  260. }
  261.  
  262. /* Initialize an empty list of function parameter names.
  263.  */
  264. void
  265. new_ident_list (param_list)
  266. ParameterList *param_list;
  267. {
  268.     param_list->first = param_list->last = NULL;
  269.     param_list->begin_comment = param_list->end_comment = 0;
  270.     param_list->comment = NULL;
  271. }
  272.  
  273. /* Add an item to the list of function parameter declarations but set only
  274.  * the parameter name field.
  275.  */
  276. void
  277. add_ident_list (to, from, name)
  278. ParameterList *to, *from;
  279. char *name;
  280. {
  281.     Parameter *p;
  282.     Declarator *declarator;
  283.  
  284.     declarator = new_declarator(name, name, 0L);
  285.     p = new_parameter(NULL, declarator);
  286.  
  287.     to->first = from->first;
  288.     if (to->first == NULL) {
  289.     to->first = p;
  290.     } else {
  291.     from->last->next = p;
  292.     }
  293.     to->last = p;
  294.     p->next = NULL;
  295. }
  296.  
  297. /* Search the list of parameters for a matching parameter name.
  298.  * Return a pointer to the matching parameter or NULL if not found.
  299.  */
  300. static Parameter *
  301. search_parameter_list (params, name)
  302. ParameterList *params;
  303. char *name;
  304. {
  305.     Parameter *p;
  306.  
  307.     for (p = params->first; p != NULL; p = p->next) {
  308.     if (strcmp(p->declarator->name, name) == 0)
  309.         return p;
  310.     }
  311.     return (Parameter *)NULL;
  312. }
  313.  
  314. /* For each name in the declarator list <declarators>, set the declaration
  315.  * specifier part of the parameter in <params> having the same name.
  316.  * This is also where we promote formal parameters.  Parameters of type
  317.  * "char", "unsigned char", "short", or "unsigned short" are promoted to
  318.  * "int".  Parameters of type "float" are promoted to "double".
  319.  */
  320. void
  321. set_param_types (params, decl_spec, declarators)
  322. ParameterList *params;
  323. DeclSpec *decl_spec;
  324. DeclaratorList *declarators;
  325. {
  326.     Declarator *d;
  327.     Parameter *p;
  328.     char *decl_spec_text;
  329.  
  330.     for (d = declarators->first; d != NULL; d = d->next) {
  331.     /* Search the parameter list for a matching name. */
  332.     if ((p = search_parameter_list(params, d->name)) == NULL) {
  333.         put_error();
  334.         fprintf(stderr, "declared argument \"%s\" is missing\n", d->name);
  335.     } else {
  336.         decl_spec_text = decl_spec->text;
  337.         if (promote_param && strcmp(d->text, d->name) == 0) {
  338.         if (decl_spec->flags & (DS_CHAR | DS_SHORT))
  339.             decl_spec_text = "int";
  340.         else if (decl_spec->flags & DS_FLOAT)
  341.             decl_spec_text = "double";
  342.         }
  343.         free(p->decl_spec.text);
  344.         p->decl_spec.text = xstrdup(decl_spec_text);
  345.  
  346.         free_declarator(p->declarator);
  347.         p->declarator = d;
  348.     }
  349.     }
  350. }
  351.  
  352. static void put_declarator();
  353.  
  354. /* Output a function parameter.
  355.  */
  356. static void
  357. put_parameter (outf, p)
  358. FILE *outf;
  359. Parameter *p;
  360. {
  361.     fputs(p->decl_spec.text, outf);
  362.     if (p->declarator->text[0] != '\0') {
  363.     if (strcmp(p->declarator->text, "...") != 0) {
  364.         if (proto_style != PROTO_ABSTRACT || proto_comments ||
  365.          where != FUNC_PROTO ||
  366.          strcmp(p->declarator->text, p->declarator->name) != 0)
  367.         fputc(' ', outf);
  368.     }
  369.     put_declarator(outf, p->declarator);
  370.     }
  371. }
  372.  
  373. /* Output a parameter list.
  374.  */
  375. static void
  376. put_param_list (outf, declarator)
  377. FILE *outf;
  378. Declarator *declarator;
  379. {
  380.     Parameter *p;
  381.     int f;
  382.  
  383.     p = declarator->params.first;
  384.     if (is_void_parameter(p)) {
  385.     if (p != NULL)
  386.         fputs("void", outf);
  387.     } else {
  388.     f = (declarator == func_declarator) ? format : FMT_OTHER;
  389.  
  390.     if (where == FUNC_DEF && declarator->params.comment != NULL)
  391.         fputs(declarator->params.comment, outf);
  392.         
  393.     fputs(fmt[f].first_param_prefix, outf);
  394.     put_parameter(outf, p);
  395.  
  396.     while (p->next != NULL) {
  397.         fputc(',', outf);
  398.         if (where == FUNC_DEF && p->comment != NULL)
  399.         fputs(p->comment, outf);
  400.  
  401.         p = p->next;
  402.         fputs(fmt[f].middle_param_prefix, outf);
  403.         put_parameter(outf, p);
  404.     }
  405.     if (where == FUNC_DEF && p->comment != NULL)
  406.         fputs(p->comment, outf);
  407.  
  408.     fputs(fmt[f].last_param_suffix, outf);
  409.     }
  410. }
  411.  
  412. /* Output function parameters.
  413.  */
  414. static void
  415. put_parameters (outf, declarator)
  416. FILE *outf;
  417. Declarator *declarator;
  418. {
  419.     Parameter *p;
  420.  
  421.     if (where == FUNC_DEF && func_style == FUNC_TRADITIONAL) {
  422.  
  423.     /* Output parameter name list for traditional function definition. */
  424.     p = declarator->params.first;
  425.  
  426.     /* Output paramter name list only for head function declarator. */
  427.     if (!is_void_parameter(p) && declarator == func_declarator) {
  428.         fputs(fmt[format].first_param_prefix, outf);
  429.         fputs(p->declarator->name, outf);
  430.         p = p->next;
  431.         while (p != NULL && strcmp(p->declarator->text, "...") != 0) {
  432.         fputc(',', outf);
  433.         fputs(fmt[format].middle_param_prefix, outf);
  434.         fputs(p->declarator->name, outf);
  435.         p = p->next;
  436.         }
  437.         fputs(fmt[format].last_param_suffix, outf);
  438.     }
  439.     } else {
  440.  
  441.     /* Output parameter type list. */
  442.     if (where == FUNC_PROTO && proto_style == PROTO_TRADITIONAL &&
  443.      declarator == func_declarator) {
  444.         if (proto_comments) {
  445.         fputs("/*", outf);
  446.         put_param_list(outf, declarator);
  447.         fputs("*/", outf);
  448.         }
  449.     } else {
  450.         put_param_list(outf, declarator);
  451.     }
  452.     }
  453. }
  454.  
  455. /* Output a function declarator.
  456.  */
  457. static void
  458. put_func_declarator (outf, declarator)
  459. FILE *outf;
  460. Declarator *declarator;
  461. {
  462.     char *s, *t, *decl_text;
  463.     int f;
  464.  
  465.     /* Output declarator text before function declarator place holder. */
  466.     if ((s = strstr(declarator->text, "%s")) == NULL)
  467.     return;
  468.     *s = '\0';
  469.     fputs(declarator->text, outf);
  470.  
  471.     /* Substitute place holder with function declarator. */
  472.     if (declarator->func_stack->func_def == FUNC_NONE) {
  473.  
  474.     decl_text = declarator->func_stack->text;
  475.     if (declarator->name[0] == '\0') {
  476.         fputs(decl_text, outf);
  477.     } else {
  478.  
  479.         /* Output the declarator text before the declarator name. */
  480.         if ((t = strstr(decl_text, declarator->name)) == NULL)
  481.         return;
  482.         *t = '\0';
  483.         fputs(decl_text, outf);
  484.         *t = declarator->name[0];
  485.  
  486.         /* Output the declarator prefix before the name. */
  487.         f = (declarator == func_declarator) ? format : FMT_OTHER;
  488.         if (strcmp(fmt[f].declarator_prefix, " ") != 0)
  489.         fputs(fmt[f].declarator_prefix, outf);
  490.  
  491.         /* Output the declarator name. */
  492.         if (where == FUNC_PROTO && proto_style == PROTO_ABSTRACT &&
  493.          declarator != func_declarator) {
  494.         if (proto_comments) {
  495.             fputs("/*", outf);
  496.             fputs(declarator->name, outf);
  497.             fputs("*/", outf);
  498.         }
  499.         } else {
  500.         fputs(declarator->name, outf);
  501.         }
  502.  
  503.         /* Output the remaining declarator text. */
  504.         fputs(t + strlen(declarator->name), outf);
  505.  
  506.         /* Output the declarator suffix. */
  507.         fputs(fmt[f].declarator_suffix, outf);
  508.     }
  509.     } else {
  510.     put_func_declarator(outf, declarator->func_stack);
  511.     }
  512.     *s = '%';
  513.     s += 2;
  514.  
  515.     /* Output declarator text up to but before parameters place holder. */
  516.     if ((t = strstr(s, "()")) == NULL)
  517.     return;
  518.     *t = '\0';
  519.     fputs(s, outf);
  520.  
  521.     if (where == FUNC_PROTO && declarator == func_declarator && proto_macro) {
  522.     fprintf(outf, " %s(", macro_name);
  523.     }
  524.  
  525.     /* Substitute place holder with function parameters. */
  526.     fputc(*t++ = '(', outf);
  527.     put_parameters(outf, declarator);
  528.     fputs(t, outf);
  529.  
  530.     if (where == FUNC_PROTO && declarator == func_declarator && proto_macro) {
  531.     fputc(')', outf);
  532.     }
  533. }
  534.  
  535. /* Output a declarator.
  536.  */
  537. static void
  538. put_declarator (outf, declarator)
  539. FILE *outf;
  540. Declarator *declarator;
  541. {
  542.     char *s;
  543.  
  544.     if (declarator->func_def == FUNC_NONE) {
  545.     if (where == FUNC_PROTO && proto_style == PROTO_ABSTRACT &&
  546.      declarator->name[0] != '\0') {
  547.         if ((s = strstr(declarator->text, declarator->name)) == NULL)
  548.         return;
  549.         *s = '\0';
  550.         if (proto_comments) {
  551.         fprintf(outf, "%s/*%s*/%s", declarator->text, declarator->name,
  552.          s + strlen(declarator->name));
  553.         } else {
  554.         fprintf(outf, "%s%s", declarator->text,
  555.          s + strlen(declarator->name));
  556.         }
  557.         *s = declarator->name[0];
  558.     } else {
  559.         fputs(declarator->text, outf);
  560.     }
  561.     } else {
  562.     put_func_declarator(outf, declarator);
  563.     }
  564. }
  565.  
  566. /* Output a declaration specifier for an external declaration.
  567.  */
  568. static void
  569. put_decl_spec (outf, decl_spec)
  570. FILE *outf;
  571. DeclSpec *decl_spec;
  572. {
  573.     if (extern_out && !(decl_spec->flags & DS_STATIC) &&
  574.      strstr(decl_spec->text, "extern") == NULL)
  575.     fputs("extern ", outf);
  576.     fputs(decl_spec->text, outf);
  577.     fputc(' ', outf);
  578. }
  579.  
  580. /* Generate variable declarations.
  581.  */
  582. void
  583. gen_declarations (decl_spec, decl_list)
  584. DeclSpec *decl_spec;        /* declaration specifier */
  585. DeclaratorList *decl_list;    /* list of declared variables */
  586. {
  587.     Declarator *d;
  588.  
  589.     if (!variables_out || (decl_spec->flags & (DS_EXTERN|DS_JUNK)))
  590.     return;
  591.     if (!static_out && (decl_spec->flags & DS_STATIC))
  592.     return;
  593.  
  594.     check_untagged(decl_spec);
  595.     func_declarator = NULL;
  596.     where = FUNC_OTHER;
  597.     format = FMT_OTHER;
  598.     for (d = decl_list->first; d != NULL; d = d->next) {
  599.     if (d->func_def == FUNC_NONE || d->head->func_stack->pointer) {
  600.         fputs(fmt[FMT_PROTO].decl_spec_prefix, stdout);
  601.         put_decl_spec(stdout, decl_spec);
  602.         put_declarator(stdout, d);
  603.         fputs(";\n", stdout);
  604.     }
  605.     }
  606. }
  607.  
  608. /* Return TRUE if the function uses varargs.
  609.  */
  610. static int
  611. uses_varargs (declarator)
  612. Declarator *declarator;
  613. {
  614.     Parameter *p;
  615.  
  616.     return (p = declarator->params.first) != NULL && p->next == NULL &&
  617.     strcmp(p->declarator->name, "va_alist") == 0;
  618. }
  619.  
  620. /* If the parameter list is empty, then replace it with "void".
  621.  */
  622. static void
  623. check_void_param (declarator)
  624. Declarator *declarator;
  625. {
  626.     DeclSpec decl_spec;
  627.     Parameter *p;
  628.  
  629.     if (declarator->params.first == NULL) {
  630.     new_decl_spec(&decl_spec, "void", 0L, DS_NONE);
  631.     p = new_parameter(&decl_spec, NULL);
  632.     new_param_list(&declarator->params, p);
  633.     }
  634. }
  635.  
  636. /* If a parameter name appears in the parameter list of a traditional style
  637.  * function definition but is not declared in the parameter declarations,
  638.  * then assign it the default type "int".
  639.  */
  640. static void
  641. set_param_decl_spec (declarator)
  642. Declarator *declarator;
  643. {
  644.     Parameter *p;
  645.  
  646.     for (p = declarator->params.first; p != NULL; p = p->next) {
  647.     if (p->decl_spec.text[0] == '\0' &&
  648.      strcmp(p->declarator->text, "...") != 0) {
  649.         free(p->decl_spec.text);
  650.         p->decl_spec.text = xstrdup("int");
  651.     }
  652.     }
  653. }
  654.  
  655. /* Generate a function prototype.
  656.  */
  657. void
  658. gen_prototype (decl_spec, declarator)
  659. DeclSpec *decl_spec;
  660. Declarator *declarator;
  661. {
  662.     if (proto_style == PROTO_NONE || (decl_spec->flags & DS_JUNK))
  663.     return;
  664.     if (!static_out && (decl_spec->flags & DS_STATIC))
  665.     return;
  666.  
  667.     func_declarator = declarator->head;
  668.     if (uses_varargs(func_declarator)) {
  669.     /* Generate a prototype for a function that uses varargs by replacing
  670.      * the "va_alist" parameter with an empty parameter list.
  671.      */
  672.     free_param_list(&func_declarator->params);
  673.     func_declarator->params.first = NULL;
  674.     }
  675.  
  676.     check_void_param(func_declarator);
  677.     set_param_decl_spec(func_declarator);
  678.  
  679.     where = FUNC_PROTO;
  680.     format = FMT_PROTO;
  681.     fputs(fmt[format].decl_spec_prefix, stdout);
  682.     put_decl_spec(stdout, decl_spec);
  683.     put_func_declarator(stdout, declarator);
  684.     fputs(";\n", stdout);
  685. }
  686.  
  687. /* Generate a declarator for a function pointer declarator or prototype.
  688.  */
  689. void
  690. gen_func_declarator (declarator)
  691. Declarator *declarator;
  692. {
  693.     /* Go to the beginning of the function declarator in the temporary
  694.      * file and overwrite it with the converted declarator.
  695.      */
  696.     fseek(cur_tmp_file(), declarator->begin, 0);
  697.     func_declarator = NULL;
  698.     where = FUNC_DEF;
  699.     format = FMT_FUNC;
  700.     put_func_declarator(cur_tmp_file(), declarator);
  701.     cur_file_changed();
  702. }
  703.  
  704. /* Output parameter declarations for old style function definition.
  705.  */
  706. static void
  707. put_param_decl (declarator)
  708. Declarator *declarator;
  709. {
  710.     Parameter *p;
  711.  
  712.     p = declarator->params.first;
  713.     if (!is_void_parameter(p)) {
  714.     fputc('\n', cur_tmp_file());
  715.     put_parameter(cur_tmp_file(), p);
  716.     fputc(';', cur_tmp_file());
  717.     p = p->next;
  718.     while (p != NULL && strcmp(p->declarator->text, "...") != 0) {
  719.         fputc('\n', cur_tmp_file());
  720.         put_parameter(cur_tmp_file(), p);
  721.         fputc(';', cur_tmp_file());
  722.         p = p->next;
  723.     }
  724.     }
  725. }
  726.  
  727. /* Generate a function definition head.
  728.  */
  729. void
  730. gen_func_definition (decl_spec, declarator)
  731. DeclSpec *decl_spec;
  732. Declarator *declarator;
  733. {
  734.     Parameter *p;
  735.     ParameterList *params;
  736.     char *comment;
  737.     int comment_len, n;
  738.  
  739.     /* Do nothing if the function is already defined in the desired style
  740.      * or if the function uses varargs.
  741.      */
  742.     func_declarator = declarator->head;
  743.     if (func_declarator->func_def == func_style ||
  744.     uses_varargs(func_declarator))
  745.     return;
  746.  
  747.     /* Save the text between the function head and the function body.
  748.      * Read the temporary file from after the last ) or ; to the
  749.      * end of the file.
  750.      */
  751.     comment_len = (int)(ftell(cur_tmp_file()) - cur_begin_comment());
  752.     comment = xmalloc(comment_len);
  753.     fseek(cur_tmp_file(), cur_begin_comment(), 0);
  754.     fread(comment, sizeof(char), comment_len, cur_tmp_file());
  755.  
  756.     format = FMT_FUNC;
  757.     if (func_declarator->func_def == FUNC_TRADITIONAL) {
  758.     /* Save the text before the parameter declarations. */
  759.     params = &func_declarator->params;
  760.     n = (int)(params->end_comment - params->begin_comment);
  761.     if (n > 0) {
  762.         params->comment = xmalloc(n+1);
  763.         fseek(cur_tmp_file(), params->begin_comment, 0);
  764.         fread(params->comment, sizeof(char), n, cur_tmp_file());
  765.         params->comment[n] = '\0';
  766.         format = FMT_FUNC_COMMENT;
  767.     }
  768.  
  769.     /* Get the parameter comments. */
  770.     for (p = func_declarator->params.first; p != NULL; p = p->next) {
  771.         n = (int)(p->declarator->end_comment - p->declarator->begin_comment);
  772.         if (n > 0) {
  773.             p->comment = xmalloc(n+1);
  774.             fseek(cur_tmp_file(), p->declarator->begin_comment, 0);
  775.             fread(p->comment, sizeof(char), n, cur_tmp_file());
  776.             p->comment[n] = '\0';
  777.             format = FMT_FUNC_COMMENT;
  778.         }
  779.     }
  780.     }
  781.  
  782.     check_void_param(func_declarator);
  783.     set_param_decl_spec(func_declarator);
  784.  
  785.     /* Go to the beginning of the function head in the temporary file
  786.      * and overwrite it with the converted function head.
  787.      */
  788.     where = FUNC_DEF;
  789.     fseek(cur_tmp_file(), decl_spec->begin, 0);
  790.  
  791.     if (func_style == FUNC_BOTH) {
  792.     char *cur_func;
  793.     int func_len;
  794.  
  795.     /* Save the current function definition head. */
  796.     func_len = (int)(cur_begin_comment() - decl_spec->begin);
  797.     cur_func = xmalloc(func_len);
  798.     fread(cur_func, sizeof(char), func_len, cur_tmp_file());
  799.  
  800.     fseek(cur_tmp_file(), decl_spec->begin, 0);
  801.     fprintf(cur_tmp_file(), "%s\n\n", func_directive);
  802.  
  803.     /* Output new style function definition head. */
  804.     if (func_declarator->func_def == FUNC_ANSI) {
  805.         fwrite(cur_func, sizeof(char), func_len, cur_tmp_file());
  806.     } else {
  807.         fputs(fmt[format].decl_spec_prefix, cur_tmp_file());
  808.         fputs(decl_spec->text, cur_tmp_file());
  809.         fputc(' ', cur_tmp_file());
  810.  
  811.         func_style = FUNC_ANSI;
  812.         put_func_declarator(cur_tmp_file(), declarator);
  813.     }
  814.     fputs("\n#else\n\n", cur_tmp_file());
  815.  
  816.     /* Output old style function definition head. */
  817.     if (func_declarator->func_def == FUNC_TRADITIONAL) {
  818.         fwrite(cur_func, sizeof(char), func_len, cur_tmp_file());
  819.     } else {
  820.         fputs(fmt[format].decl_spec_prefix, cur_tmp_file());
  821.         fputs(decl_spec->text, cur_tmp_file());
  822.         fputc(' ', cur_tmp_file());
  823.  
  824.          format = FMT_FUNC;
  825.         func_style = FUNC_TRADITIONAL;
  826.         put_func_declarator(cur_tmp_file(), declarator);
  827.         put_param_decl(func_declarator);
  828.     }
  829.  
  830.     fputs("\n#endif", cur_tmp_file());
  831.     if (*comment != '\n')
  832.         fputc('\n', cur_tmp_file());
  833.     func_style = FUNC_BOTH;
  834.     free(cur_func);
  835.  
  836.     } else {
  837.     /* Output declarator specifiers. */
  838.     fputs(fmt[format].decl_spec_prefix, cur_tmp_file());
  839.     fputs(decl_spec->text, cur_tmp_file());
  840.     fputc(' ', cur_tmp_file());
  841.  
  842.     /* Output function declarator. */
  843.     put_func_declarator(cur_tmp_file(), declarator);
  844.     if (func_style == FUNC_TRADITIONAL)
  845.         put_param_decl(func_declarator);
  846.     }
  847.  
  848.     /* Output text between function head and body. */
  849.     fwrite(comment, sizeof(char), comment_len, cur_tmp_file());
  850.     free(comment);
  851.  
  852.     cur_file_changed();
  853. }
  854.